package com.northpool.operator.dataset.spatial;

import com.northpool.operator.annotation.InputParam;
import com.northpool.operator.annotation.InputParams;
import com.northpool.operator.annotation.OperatorInfo;
import com.northpool.operator.annotation.ParamEnum;
import com.northpool.operator.annotation.ParamEnums;
import com.northpool.operator.common.algorithm.OperatorTestBuild;
import com.northpool.operator.common.algorithm.TestParamBuilder;
import com.northpool.operator.common.database.DatabaseUtils;
import com.northpool.operator.exception.ParamException;
import com.northpool.operator.param.ParamTool;
import com.northpool.operator.type.TypeEnum;
import com.northpool.operator.utils.StpOperatorHelper;
import com.northpool.resources.datasource.IDataSource;
import com.northpool.resources.datasource.db.DbDataSource;
import com.northpool.resources.datatable.operate.ITableOperator;
import org.apache.commons.lang3.StringUtils;

import java.util.List;

@OperatorInfo(
        ref = "SridChangeOperator",
        name = "空间信息变更",
        description = "postgres、kingbase、highgo空间表的空间信息变更，只变更空间字段的元数据，对实际空间数据无影响",
        enums = {
                @ParamEnums(ref = "spatialType", value = {
                        @ParamEnum(ref = "MultiPolygon", name = "MultiPolygon", description = "多部件面"),
                        @ParamEnum(ref = "MultiPolyline", name = "MultiPolyline", description = "多部件线"),
                        @ParamEnum(ref = "MultiPoint", name = "MultiPoint", description = "多部件点"),
                        @ParamEnum(ref = "Polygon", name = "Polygon", description = "面"),
                        @ParamEnum(ref = "Polyline", name = "Polyline", description = "线"),
                        @ParamEnum(ref = "Point", name = "Point", description = "点"),
                        @ParamEnum(ref = "Geometry", name = "Geometry", description = "未知"),
                })
        }
)
public class SridChangeOperator extends StpOperatorHelper {

    @InputParams({
            @InputParam(ref = "datasource", name = "数据源", desc = "数据源ID", type = TypeEnum.DATASOURCE, required = true),
            @InputParam(ref = "tableName", name = "表名称", desc = "数据表名称，如: tb_test", type = TypeEnum.STRING, required = true),
            @InputParam(ref = "spatialField", name = "空间字段名称", desc = "数据表名称，如: tb_test", type = TypeEnum.STRING, required = false),
            @InputParam(ref = "srid", name = "目标SRID", desc = "目标SRID", type = TypeEnum.NUMBER, required = true),
            @InputParam(ref = "spatialType", name = "几何类型", desc = "空间字段的目标几何类型", type = TypeEnum.ENUM, enumRef = "spatialType", required = true)
    })
    public SridChangeOperator() {
    }

    public static void main(String[] args) {
        OperatorTestBuild.execute(SridChangeOperator.class, TestParamBuilder.aBuilder()
                .param("datasource", "test_bcg")
                .param("tableName", "public.dltb_building_b_all")
                .param("spatialField", "geom")
                .param("srid", "4326")
                .param("spatialType", "MultiPolygon")
                .build());
    }

    @Override
    public void execute(ParamTool paramTool) throws Exception {
        String dataSourceId = paramTool.getStr("datasource");
        String dataSourceJson = DatabaseUtils.getDataSourceJson(dataSourceId);
        String tableName = paramTool.getStr("tableName");
        String spatialField = paramTool.getStr("spatialField");
        String spatialType = paramTool.getStr("spatialType");
        IDataSource ds = IDataSource.fromJSON(dataSourceJson);
        DbDataSource dbDataSource;
        if (ds instanceof DbDataSource) {
            dbDataSource = (DbDataSource) ds;
        } else {
            throw new ParamException("数据源", "数据源仅支持：postgres、kingbase、highgo");
        }
        ITableOperator tableOperator = ds.getTableOperator(tableName);
        List<String> spatialColumnList = tableOperator.getSpatialColumnList();
        if (spatialColumnList.isEmpty()) {
            this.error("数据表 {} 空间字段未找到", tableName);
            this.failedExit();
        } else if (spatialColumnList.size() > 1 && StringUtils.isBlank(spatialField)) {
            throw new ParamException("空间字段名称", "数据表存在多个空间字段时需指定空间字段名称");
        }
        if (StringUtils.isBlank(spatialField)) {
            spatialField = spatialColumnList.get(0);
        }

//        ALTER TABLE "DLG_BOUA_CUN_2022"
//        ALTER COLUMN "Shape" TYPE geometry(MultiPolygon, 4490);
        String sql = "ALTER TABLE " + tableName
                + " ALTER COLUMN " + spatialField + " TYPE geometry(" + spatialType + ", " + paramTool.getStr("srid") + ")";
        dbDataSource.executeSql(sql);

        this.log("空间信息变更成功");
    }
}
